#pragma once

#include <AVUIItemStructList.h>
#include <AVUIObjectCollection.h>

namespace AVUI {

template <class T>
class ValueTypeCollection : public Freezable, public ICollection
{
public:

	const T& operator [] (int i) const { return m_items[i]; }
	T& operator [] (int i) { return m_items[i]; }

	void Add(const T& t) { m_items.AddItem(t); }
	void Insert(int idx, const T& t) { m_items.Insert(idx, t); }

    virtual bool get_IsEmpty() { return m_items.IsEmpty(); }
    virtual int get_Count() { return m_items.get_Count(); }
    virtual void Clear() { m_items.Clear(); }
    virtual void Add(Object* pObject) { m_items.AddItem(UnboxValue<T>(pObject)); }
	virtual void Insert(int idx, Object* pObject) { m_items.Insert(idx, UnboxValue<T>(pObject)); }
    virtual bool Contains(Object* pObject) { return m_items.Contains(UnboxValue<T>(pObject)); }
    virtual void Move(int oldIndex, int newIndex) { return m_items.Move(oldIndex, newIndex); }
    virtual bool Remove(Object* pObject) { return m_items.Remove(UnboxValue<T>(pObject)); }
    virtual void RemoveRange(int idx, int count) { for(int removeIdx = 0; removeIdx < count; removeIdx++) m_items.RemoveAt(removeIdx); }
    virtual void RemoveAt(int idx) { m_items.RemoveAt(idx); };
    virtual TRefCountedPtr<Object> GetItemAt(int idx) { return BoxValue<T>(m_items[idx]); }
    virtual void SetItemAt(int idx, Object* pValue) { m_items[idx] = UnboxValue<T>(pValue); }
    virtual int IndexOf(Object* pObject) { if(pObject->get_Type() != AVUI::get_Type((T*) 0)) return -1; return m_items.IndexOf(UnboxValue<T>(pObject)); }
    virtual ObjectPtr GetEnumerator() { return (Object*)object_allocate<CollectionEnumerator>(this); }
    virtual Object* get_Object() { return Object::get_Object(); }

	// TODO -- Change Notification
	void set_NotifyOnChange(bool notifyOnChange) { }

    virtual void CloneCore(Freezable* pSource) AVUI_OVERRIDE
    {
        ValueTypeCollection<T>* pCollectionSource = (ValueTypeCollection<T>*) pSource;
        Freezable::CloneCore(pSource);
    
        for(int idx = 0; idx < pCollectionSource->get_Count(); idx++)
        {
            Add((*pCollectionSource)[idx]);
        }
    
    }

    virtual void GetAsFrozenCore(Freezable* pSource) AVUI_OVERRIDE
    {
        ValueTypeCollection<T>* pCollectionSource = (ValueTypeCollection<T>*) pSource;
        Freezable::GetAsFrozenCore(pSource);

        for(int idx = 0; idx < pCollectionSource->get_Count(); idx++)
        {
            Add((*pCollectionSource)[idx]);
        }
    }

private:

	ItemStructList<T> m_items;
};


}; // namespace AVUI
